<?php

namespace App\Jobs;

use App\Http\Controllers\Api\Repositories\PostsRepositores;
use App\Http\Controllers\Api\Repositories\WxCommentRepositores;
use App\Models\Posts\WxPost;
use App\Models\WxDegreeIncrement;
use App\Wen\Utils\RealtimeUtils;
use App\Wen\Utils\Settings;
use App\Wen\Utils\StatisticUtils;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Redis;

class RealtimePostsDegreeJob implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
    protected $size = 100;
    public $tries = 1;
    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($size = 100)
    {
        //
        if($size){
            $this->size = $size;
        }
    }

    public function para_W($post_id){
        $like_count = PostsRepositores::likeCont($post_id); // 笔记喜欢数量
        $comment_count = WxCommentRepositores::commentCount($post_id);//评论数量
        $post_be_collected = StatisticUtils::post_becollected_count($post_id);
        $W = 0.2 * log($like_count + 1) + 0.5 * $comment_count + 0.3 * $post_be_collected;
        return $W;
    }

    public function para_I($post_user_id){
        $author_fans = StatisticUtils::user_fans_count($post_user_id);
        $author_be_likes = StatisticUtils::user_beliked_count($post_user_id);
        $author_post_count = StatisticUtils::user_post_count($post_user_id);
        $author_be_collected = StatisticUtils::user_becollected_count($post_user_id);
        $I = 0.4 * log($author_fans + 1) + 0.1 * log($author_be_likes + 1) + 0.2 * $author_post_count + 0.3 * $author_be_collected;
        return $I;
    }

    public function update_H(&$post){
        if(_empty_($post)){
            return;
        }
        $old_degree = $post->degree ?? 0;
        $post_id = $post->id;
        if(_empty_($post_id)){
            return;
        }
        $post_user_id = $post->user_id;
        $created_at = ($post->created_at)->toDateTimeString();

        $W = $this->para_W($post_id);
        $I = $this->para_I($post_user_id);
        $T = (time() - strtotime($created_at)) / 3600;
        $G = 1.3;
        $H = round(( $W + 0.5 * $I ) / pow($T + 1, $G), 2);

        WxPost::withoutSyncingToSearch(function () use (&$post, $H){
            $post->degree = $H;
            $post->save();
        });

        // 计算增量
        $degree_increment = $H - $old_degree;
        RealtimeUtils::add_object_degree($post_id, 1, $degree_increment);
        return true;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //Redis::sadd('realtime:post:set', 'c');
        //        dd(Redis::smembers('test111'));
        global $__MINI_GLOBAL_TENANTS_ARR__;
        foreach ($__MINI_GLOBAL_TENANTS_ARR__ as $tenant_id){
            $posts_ids = WxPost::where('posts_state', 0)->where('tenant_id', $tenant_id)->orderBy('degree', 'desc')->limit($this->size)->pluck('id')->toArray();
            if($posts_ids){
                foreach ($posts_ids as $post_id){
                    Redis::sadd('realtime:post:set', $post_id);
                }
            }
        }



        $todo_set = Redis::smembers('realtime:post:set');
        if($todo_set){
            foreach ($todo_set as $post_id){
                if(_empty_($post_id)){
                    continue;
                }
                RealtimeUtils::add_object_degree($post_id, 1, 1);
                $post = WxPost::where('id', $post_id)->first(['id','user_id', 'created_at','degree', 'circle_id']);
                $this->update_H($post);
            }
            Redis::del('realtime:post:set');
        }else{
            _logger_(__file__, __line__, 'realtime:post:set == null');
        }


        // 同时处理热度增量对象集合

        // Redis::sadd('realtime:others:set', json_encode([$object_id, $type, $degree]));
        Redis::del('realtime:others:list');
        $others_todo_list = Redis::smembers('realtime:others:set');
        if($others_todo_list){
            foreach ($others_todo_list as $todo_item){
                $object = json_decode($todo_item, true);
                RealtimeUtils::add_object_degree( $object[0], $object[1], $object[2] );
            }
            Redis::del('realtime:others:set');
        }

        foreach ($__MINI_GLOBAL_TENANTS_ARR__ as $tenant_id){
            Cache::forget('realtime:get_top_posts:50:'.$tenant_id);
        }
        // 清理笔记增量增量 （1:笔记 2:圈子 3:商品 4:用户 5:话题）
        $type_1_newest_time = WxDegreeIncrement::where('type', 1)->orderBy('id', 'desc')->value('created_at');
        $type_2_newest_time = WxDegreeIncrement::where('type', 2)->orderBy('id', 'desc')->value('created_at');
        $type_3_newest_time = WxDegreeIncrement::where('type', 3)->orderBy('id', 'desc')->value('created_at');
        $type_4_newest_time = WxDegreeIncrement::where('type', 4)->orderBy('id', 'desc')->value('created_at');
        $type_5_newest_time = WxDegreeIncrement::where('type', 5)->orderBy('id', 'desc')->value('created_at');
        if($type_1_newest_time){
            WxDegreeIncrement::where([ ['type', '=', 1],['created_at', '<', $type_1_newest_time->subDays(Settings::get('realtime_post_degree_increment_keep_days', 5))] ])->delete();
        }
        if($type_2_newest_time){
            WxDegreeIncrement::where([ ['type', '=', 2],['created_at', '<', $type_2_newest_time->subDays(Settings::get('realtime_circle_degree_increment_keep_days', 10))] ])->delete();
        }
        if($type_3_newest_time){
            WxDegreeIncrement::where([ ['type', '=', 3],['created_at', '<', $type_3_newest_time->subDays(Settings::get('realtime_goods_degree_increment_keep_days', 10))] ])->delete();
        }
        if($type_4_newest_time){
            WxDegreeIncrement::where([ ['type', '=', 4],['created_at', '<', $type_4_newest_time->subDays(Settings::get('realtime_user_degree_increment_keep_days', 10))] ])->delete();
        }
        if($type_5_newest_time){
            WxDegreeIncrement::where([ ['type', '=', 5],['created_at', '<', $type_5_newest_time->subDays(Settings::get('realtime_topic_degree_increment_keep_days', 10))] ])->delete();
        }

        RealtimeTopAndFlowJob::dispatch();
    }
}
